﻿using System;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Salient.Web.Administration.AppConfig
{
    public partial class ManageAppSettings : ApplicationConfigurationPage
    {
        #region LocationType enum

        public enum LocationType
        {
            Local = 0,
            Inherited = 1,
            Overridden = 2,
        }

        #endregion

        private WebAdminWithConfirmation Master
        {
            get { return (WebAdminWithConfirmation) base.Master; }
        }

        private void AddAppSettingRow(DataTable dataTable, string name, string value, LocationType locationType)
        {
            DataRow row = dataTable.NewRow();

            // Assume the columns are in expected order when the table is created
            row[0] = name;
            row[1] = value;
            row[2] = locationType;

            dataTable.Rows.Add(row);
        }

        private void BindAppSettings()
        {
            // TODO: Perf: It might not be needed if there are no application settings.

            var dataTable = new DataTable();
            dataTable.Locale = CultureInfo.InvariantCulture; // FxCop

            dataTable.Columns.Add("Name", typeof (string));
            dataTable.Columns.Add("Value", typeof (string));
            dataTable.Columns.Add("LocationType", typeof (LocationType));

            string appPath = ApplicationPath;
            string parentPath = GetParentPath(appPath);

            System.Configuration.Configuration parentConfig = OpenWebConfiguration(parentPath);
            var parentAppSettingsSection = (AppSettingsSection) parentConfig.GetSection("appSettings");
            KeyValueConfigurationCollection parentSettings = parentAppSettingsSection.Settings;

            System.Configuration.Configuration config = OpenWebConfiguration(appPath);
            var appSettingsSection = (AppSettingsSection) config.GetSection("appSettings");
            KeyValueConfigurationCollection settings = appSettingsSection.Settings;

            foreach (KeyValueConfigurationElement element in settings)
            {
                string name = element.Key;
                string value = element.Value;
                KeyValueConfigurationElement parentValue = parentSettings[name];
                if (parentValue != null && parentValue.Value != value)
                {
                    AddAppSettingRow(dataTable, name, value, LocationType.Overridden);
                    parentSettings.Remove(name);
                }
                else if (parentValue == null)
                {
                    AddAppSettingRow(dataTable, name, value, LocationType.Local);
                }
                else
                {
                    // we have something which is getting inherited but not getting overridden...
                    AddAppSettingRow(dataTable, name, value, LocationType.Inherited);
                }
            }

            var dataView = new DataView(dataTable);
            dataView.Sort = "Name ASC";

            AppSettingGridView.DataSource = dataView;
            AppSettingGridView.DataBind();

            // Display the label of # of app settings
            int totalCount = dataView.Count;
            string numOfAppSettingsText = String.Format((string) GetLocalResourceObject("NumOfAppSettingsText"),
                                                        totalCount.ToString(CultureInfo.InvariantCulture));
            if (totalCount <= AppSettingGridView.PageSize)
            {
                NumOfAppSettingsLabel.Visible = true;
                NumOfAppSettingsLabel.Text = numOfAppSettingsText;
            }
            else
            {
                // Merge the text in the pager row
                NumOfAppSettingsLabel.Visible = false;

                var labelCell = new TableCell();
                labelCell.HorizontalAlign = DirectionalityHorizontalAlign;
                labelCell.VerticalAlign = VerticalAlign.Top;
                labelCell.ColumnSpan = 4;
                labelCell.Text = numOfAppSettingsText;

                GridViewRow pagerRow = AppSettingGridView.BottomPagerRow;
                TableCell pagerCell = pagerRow.Cells[0];
                pagerCell.ColumnSpan -= 4;
                pagerRow.Cells.AddAt(0, labelCell);
            }
        }

        public string GetToolTip(string resourceName, string itemName)
        {
            var tempString = (string) GetLocalResourceObject(resourceName);
            return String.Format((string) GetGlobalResourceObject("GlobalResources", "ToolTipFormat"), tempString,
                                 itemName);
        }

        public string GetLocationTypeText(LocationType locationType)
        {
            string resourceName = PropertyConverter.EnumToString(typeof (LocationType), locationType);
            return ((string) GetLocalResourceObject(resourceName));
        }

        private void Page_Load()
        {
            if (!IsPostBack)
            {
                string appPath = ApplicationPath;
                if (!String.IsNullOrEmpty(appPath))
                {
                    MainTitle.Text = String.Format((string) GetLocalResourceObject("TitleForSite"), appPath);
                }

                BindAppSettings();

                AppSettingGridView.HeaderStyle.HorizontalAlign = DirectionalityHorizontalAlign;
            }
        }

        public void AppSettingGridView_Delete(object sender, GridViewDeleteEventArgs e)
        {
            GridViewRow row = AppSettingGridView.Rows[e.RowIndex];
            TableCell nameCell = row.Cells[1];
            Name.Value = HttpUtility.HtmlDecode(nameCell.Text);
            DeleteName.Text = String.Format((string) GetLocalResourceObject("ConfirmationText"), nameCell.Text);

            // Go to confirmation UI
            Master.SetDisplayUI(true);
        }

        public void AppSettingGridView_Edit(object sender, GridViewEditEventArgs e)
        {
            var editUrl = new StringBuilder();
            editUrl.Append("EditAppSetting.aspx");

            GridViewRow row = AppSettingGridView.Rows[e.NewEditIndex];
            TableCell nameCell = row.Cells[1];
            TableCell valueCell = row.Cells[2];

            string tempString = HttpUtility.HtmlDecode(nameCell.Text);
            editUrl.Append("?name=");
            tempString = HttpUtility.UrlEncode(tempString);

            editUrl.Append(tempString);

            tempString = HttpUtility.HtmlDecode(valueCell.Text);
            editUrl.Append("&value=");
            tempString = HttpUtility.UrlEncode(tempString);

            editUrl.Append(tempString);

            Response.Redirect(editUrl.ToString());
        }

        public void AppSettingGridView_PageIndexChanged(object sender, GridViewPageEventArgs e)
        {
            AppSettingGridView.PageIndex = e.NewPageIndex;
            BindAppSettings();
        }

        // Confirmation's related handlers
        public void Yes_Click(object sender, EventArgs e)
        {
            string appPath = ApplicationPath;
            string parentPath = GetParentPath(appPath);

            System.Configuration.Configuration parentConfig = OpenWebConfiguration(parentPath);
            var parentAppSettingsSection = (AppSettingsSection) parentConfig.GetSection("appSettings");
            KeyValueConfigurationCollection parentSettings = parentAppSettingsSection.Settings;

            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
            var appSettingsSection = (AppSettingsSection) config.GetSection("appSettings");

            // check if this is an inherited setting that
            // we are trying to remove.
            KeyValueConfigurationElement parentValue = parentSettings[Name.Value];
            if (parentValue != null)
            {
                // add an identical entry that the parent already has, so local entry gets deleted
                if (appSettingsSection.Settings[Name.Value] == null)
                    appSettingsSection.Settings.Add(Name.Value, parentValue.Value);
                else
                    appSettingsSection.Settings[Name.Value].Value = parentValue.Value;
            }
            else
            {
                appSettingsSection.Settings.Remove(Name.Value);
            }

            SaveConfig(config);

            // Before data binding again, we need to adjust the current page index if
            // this is the last property to be deleted on this page
            if (AppSettingGridView.PageIndex != 0)
            {
                int totalCount = AppSettingGridView.Rows.Count - 1;
                if ((totalCount%AppSettingGridView.PageSize) == 0)
                {
                    AppSettingGridView.PageIndex -= 1;
                }
            }

            // Re-populate data and return to the content page
            BindAppSettings();
            Master.SetDisplayUI(false);
        }

        public void No_Click(object sender, EventArgs e)
        {
            BindAppSettings();
            Master.SetDisplayUI(false);
        }
    }
}